package org.cainiao.basic.switch_test;

/**
 * tableswitch 与 lookupswitch 指令的实现原理不同<br />
 * tableswitch 基于索引表，即将条件值当作索引表的偏移量<br />
 * lookupswitch 基于二分查找之类的查找算法<br />
 * tableswitch 可以高效地从索引表中确定 case 语句块的分支偏移量<br />
 *
 * 当 switch 语句中 case 分支条件值比较稀疏时，tableswitch 指令的空间使用率偏低<br />
 * 此时可以使用 lookupswitch<br />
 *
 * lookupswitch 指令从索引表确定分支偏移量的过程中，必须把条件值与不同的键进行比较<br />
 * 而 tableswitch 指令只需对索引值进行一次范围检查<br />
 * 因此，如果不太需要考虑空间效率，那么 tableswitch 指令会比 lookupswitch 指令有更高的执行效率<br />
 *
 * <p>
 * Author: Cai Niao(wdhlzd@163.com)<br />
 */
public class SwitchTest {

    public int test(int i) {
        /*
             0: iload_1
             1: tableswitch   { // 0 to 4
                           0: 38
                           1: 36
                           2: 42
                           3: 42
                           4: 40
                     default: 42
                }
            36: iconst_1
            37: ireturn
            38: iconst_0
            39: ireturn
            40: iconst_2
            41: ireturn
            42: iconst_m1
            43: ireturn

            tableswitch 也会将索引排序，即，虽然源码中 1 在前，但编译后 0 在前
         */
        switch (i) {
            case 1: return 1;
            case 0: return 0;
            case 4: return 2;
            default: return -1;
        }
    }

    public int test2(int i) {
        /*
             0: iload_1
             1: tableswitch   { // 0 to 4
                           0: 40
                           1: 36
                           2: 48
                           3: 48
                           4: 44
                     default: 48
                }
            36: iconst_1
            37: goto          49
            40: iconst_0
            41: goto          49
            44: iconst_2
            45: goto          49
            48: iconst_m1
            49: ireturn

            使用 switch 增强语法后，反而多了 goto 步骤
            tableswitch 也会将索引排序，即，虽然源码中 1 在前，但编译后 0 在前
         */
        return switch (i) {
            case 1 -> 1;
            case 0 -> 0;
            case 4 -> 2;
            default -> -1;
        };
    }

    public int test3(int i) {
        /*
             0: iload_1
             1: lookupswitch  { // 3
                        -100: 38
                           0: 40
                         100: 36
                     default: 42
                }
            36: iconst_1
            37: ireturn
            38: iconst_m1
            39: ireturn
            40: iconst_0
            41: ireturn
            42: bipush        -2
            44: ireturn

            lookupswitch 会将索引排序，即，虽然源码中 100 在前，但编译后 -100 在前
            这是为了能利用二分查找之类的算法来加快索引查找
         */
        switch (i) {
            case 100: return 1;
            case -100: return -1;
            case 0: return 0;
            default: return -2;
        }
    }
}
